package com.ilink.ilinkcommon.advice;

import com.ilink.ilinkcommon.domain.R;
import com.ilink.ilinkcommon.exception.BadRequestException;
import com.ilink.ilinkcommon.exception.CommonException;
import com.ilink.ilinkcommon.exception.DbException;
import com.ilink.ilinkcommon.utils.WebUtils;
import java.net.BindException;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.util.NestedServletException;

/**
 * <h3>ilink-java-backend</h3>
 *
 * @author HuangJiayu
 * @description <p>常用错误提示</p>
 * @date 2024-09-14 16:34
 **/
@RestControllerAdvice
@Slf4j
public class CommonExceptionAdvice {
	
	@ExceptionHandler(DbException.class)
	public Object handleDbException(DbException e) {
		log.error("mysql数据库操作异常 -> ", e);
		return processResponse(e);
	}
	
	@ExceptionHandler(CommonException.class)
	public Object handleBadRequestException(CommonException e) {
		log.error("自定义异常 -> {} , 异常原因：{}  ", e.getClass().getName(), e.getMessage());
		log.debug("", e);
		return processResponse(e);
	}
	
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
		String msg = e.getBindingResult().getAllErrors()
		 .stream().map(ObjectError::getDefaultMessage)
		 .collect(Collectors.joining("|"));
		log.error("请求参数校验异常 -> {}", msg);
		log.debug("", e);
		return processResponse(new BadRequestException(msg));
	}
	
	@ExceptionHandler(BindException.class)
	public Object handleBindException(BindException e) {
		log.error("请求参数绑定异常 ->BindException， {}", e.getMessage());
		log.debug("", e);
		return processResponse(new BadRequestException("请求参数格式错误"));
	}
	
	@ExceptionHandler(NestedServletException.class)
	public Object handleNestedServletException(NestedServletException e) {
		log.error("参数异常 -> NestedServletException，{}", e.getMessage());
		log.debug("", e);
		return processResponse(new BadRequestException("请求参数处理异常"));
	}
	
	@ExceptionHandler(Exception.class)
	public Object handleRuntimeException(Exception e) {
		log.error("其他异常 uri : {} -> ", WebUtils.getRequest().getRequestURI(), e);
		return processResponse(new CommonException("服务器内部异常", 500));
	}
	
	private ResponseEntity<R<Void>> processResponse(CommonException e) {
		return ResponseEntity.status(e.getCode()).body(R.error(e));
	}
}
